home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / MAP Viewer / Engine.cpp < prev    next >
C/C++ Source or Header  |  2003-10-09  |  14KB  |  631 lines

  1. /*
  2. Half-Life MAP viewing utility.
  3. Copyright (C) 2003  Ryan Samuel Gregg
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include "stdafx.h"
  21. #include "Engine.h"
  22.  
  23. CEngine::CEngine(CConfig *Config, CRichTextBox *txtConsole)
  24. {
  25.     this->Config = Config;
  26.     this->txtConsole = txtConsole;
  27.  
  28.     vMouseOld.X = 0;
  29.     vMouseOld.Y = 0;
  30.     vMouseNew.X = 0;
  31.     vMouseNew.Y = 0;
  32.  
  33.     Frustum = new CFrustum();
  34.     Camera = new CCamera();
  35.     TextureManager = NULL;
  36.     World = NULL;
  37.     HighlightObject = NULL;
  38.     PointFile = NULL;
  39. }
  40.  
  41. bool CEngine::Initialize(HWND hWND)
  42. {
  43.     this->hWND = hWND;
  44.  
  45.     int iPixelFormat;
  46.     PIXELFORMATDESCRIPTOR pfd;
  47.  
  48.     pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  49.     pfd.nVersion = 1;
  50.     pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  51.     pfd.iPixelType = PFD_TYPE_RGBA;
  52.     pfd.cColorBits = Config->bColorBits;
  53.     pfd.cRedBits = 0;
  54.     pfd.cRedShift = 0;
  55.     pfd.cGreenBits = 0;
  56.     pfd.cGreenShift = 0;
  57.     pfd.cBlueBits = 0;
  58.     pfd.cBlueShift = 0;
  59.     pfd.cAlphaBits = 0;
  60.     pfd.cAlphaShift = 0;
  61.     pfd.cAccumBits = 0;
  62.     pfd.cAccumRedBits = 0;
  63.     pfd.cAccumGreenBits = 0;
  64.     pfd.cAccumBlueBits = 0;
  65.     pfd.cAccumAlphaBits = 0;
  66.     pfd.cDepthBits = Config->bDepthBits;
  67.     pfd.cStencilBits = 0;
  68.     pfd.cAuxBuffers = 0;
  69.     pfd.iLayerType = PFD_MAIN_PLANE;
  70.     pfd.bReserved = 0;
  71.     pfd.dwLayerMask =0;
  72.     pfd.dwVisibleMask = 0;
  73.     pfd.dwDamageMask = 0;
  74.  
  75.     hDC = GetDC(hWND);
  76.  
  77.     if((iPixelFormat = ChoosePixelFormat(hDC, &pfd)) == 0)
  78.         return false;
  79.  
  80.     if(SetPixelFormat(hDC, iPixelFormat, &pfd) == false)
  81.         return false;
  82.  
  83.     if((hGLRC = wglCreateContext(hDC)) == 0)
  84.         return false;
  85.  
  86.     if(wglMakeCurrent(hDC, hGLRC) == false)
  87.         return false;
  88.  
  89.     glClearColor(Config->cBackColor.R, Config->cBackColor.G, Config->cBackColor.B, Config->cBackColor.A);
  90.     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  91.     glHint(GL_FOG_HINT, GL_NICEST);
  92.     glCullFace(GL_FRONT);
  93.     glShadeModel(GL_FLAT);
  94.  
  95.     // Lighting
  96.     float fGlobalAmbient[] = { 0.25f, 0.25f, 0.25f, 1.0f };
  97.     float fLightAmbient0[] = { 0.5f, 0.5f, 0.5f, 1.0f };
  98.     float fLightDiffuse0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  99.     float fLightSpecular0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  100.     float fLightPosition0[] = { 4096.0f, 4096.0f, 4096.0f, 0.0f };
  101.     float fMaterialSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  102.     float fMaterialEmission[] = { 0.0f, 0.0f, 0.0f, 1.0f };
  103.  
  104.     //glLightModelfv(GL_AMBIENT, fGlobalAmbient);
  105.  
  106.     glLightfv(GL_LIGHT0, GL_AMBIENT, fLightAmbient0);
  107.     glLightfv(GL_LIGHT0, GL_DIFFUSE, fLightDiffuse0);
  108.     glLightfv(GL_LIGHT0, GL_SPECULAR, fLightSpecular0);
  109.     glLightfv(GL_LIGHT0, GL_POSITION, fLightPosition0);
  110.  
  111.     float fLightAmbient1[] = { 0.25f, 0.25f, 0.25f, 1.0f };
  112.     float fLightDiffuse1[] = { 0.5f, 0.5f, 0.5f, 1.0f };
  113.     float fLightSpecular1[] = { 0.5f, 0.5f, 0.5f, 1.0f };
  114.     float fLightPosition1[] = { -4096.0f, -4096.0f, -4096.0f, 0.0f };
  115.  
  116.     glLightfv(GL_LIGHT1, GL_AMBIENT, fLightAmbient1);
  117.     glLightfv(GL_LIGHT1, GL_DIFFUSE, fLightDiffuse1);
  118.     glLightfv(GL_LIGHT1, GL_SPECULAR, fLightSpecular1);
  119.     glLightfv(GL_LIGHT1, GL_POSITION, fLightPosition1);
  120.  
  121.     glMaterialfv(GL_BACK, GL_SPECULAR, fMaterialSpecular);
  122.     glMaterialfv(GL_BACK, GL_EMISSION, fMaterialEmission);
  123.     
  124.     // Fog
  125.     switch(Config->eFogMode)
  126.     {
  127.     case FogMode::Exp:
  128.             glFogi(GL_FOG_MODE, GL_EXP);
  129.             break;
  130.     case FogMode::Exp2:
  131.             glFogi(GL_FOG_MODE, GL_EXP2);
  132.             break;
  133.     case FogMode::Linear:
  134.         default:
  135.             glFogi(GL_FOG_MODE, GL_LINEAR);
  136.             break;
  137.     }
  138.  
  139.     float fFogColor[] = { Config->cFogColor.R, Config->cFogColor.G, Config->cFogColor.B, Config->cFogColor.A };
  140.  
  141.     glFogfv(GL_FOG_COLOR, (float*)&fFogColor);
  142.     glFogf(GL_FOG_DENSITY, Config->fFogDensity);
  143.     glFogf(GL_FOG_START, Config->fFogStart);
  144.     glFogf(GL_FOG_END, Config->fFogEnd);
  145.  
  146.     BuildFont(S"Courier New");
  147.  
  148.     wglMakeCurrent(0, 0);
  149.  
  150.     return true;
  151. }
  152.  
  153. void CEngine::Destroy()
  154. {
  155.     MakeCurrent();
  156.     DestroyFont();
  157.     MakeNotCurrent();
  158.  
  159.     DestroyTextures();
  160.  
  161.     ReleaseDC(hWND, hDC);
  162.     wglDeleteContext(hGLRC);
  163. }
  164.  
  165. void CEngine::MakeCurrent()
  166. {
  167.     wglMakeCurrent(hDC, hGLRC);
  168. }
  169.  
  170. void CEngine::MakeNotCurrent()
  171. {
  172.     wglMakeCurrent(0, 0);
  173. }
  174.  
  175. void CEngine::BuildFont(String *FontName)
  176. {
  177.     HFONT Font;
  178.     HFONT OldFont;
  179.  
  180.     void *pFontName = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(FontName).ToPointer();
  181.  
  182.     iFontBase = glGenLists(96);
  183.     Font = CreateFont(-12,                                // Height
  184.                       0,                                // Width
  185.                       0,                                // Angle
  186.                       0,                                // Escape angle
  187.                       FW_BOLD,                        // Font weight
  188.                       false,                            // Italic
  189.                       false,                            // Underline
  190.                       false,                             // Strikeout
  191.                       ANSI_CHARSET,                    // Character Set Identifier
  192.                       OUT_TT_PRECIS,                    // Output Precision
  193.                       CLIP_DEFAULT_PRECIS,            // Clipping Precision
  194.                       ANTIALIASED_QUALITY,            // Output Quality
  195.                       FF_DONTCARE | DEFAULT_PITCH,    // Family And Pitch
  196.                       (LPCSTR)pFontName);                    // Font Name
  197.  
  198.     OldFont = (HFONT)SelectObject(hDC, Font);
  199.     wglUseFontBitmaps(hDC, 32, 96, iFontBase);
  200.     SelectObject(hDC, OldFont);
  201.     DeleteObject(Font);
  202.  
  203.     System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr(pFontName)));
  204. }
  205.  
  206. void CEngine::DestroyFont()
  207. {
  208.     glDeleteLists(iFontBase, 96);
  209. }
  210.  
  211. void CEngine::Resize(int iWidth, int iHeight)
  212. {
  213.     if(iWidth == 0 || iHeight == 0)
  214.         return;
  215.  
  216.     MakeCurrent();
  217.  
  218.     RECT rv;
  219.     GetClientRect(hWND, &rv);
  220.  
  221.     Frustum->SetAspect((float)(rv.right - rv.left) / (float)(rv.bottom - rv.top));
  222.     Frustum->SetWidth((float)(rv.right - rv.left));
  223.     Frustum->SetHeight((float)(rv.bottom - rv.top));
  224.  
  225.     glMatrixMode(GL_PROJECTION);
  226.     glLoadIdentity();
  227.     gluPerspective(Config->fFrustumFieldOfView, Frustum->GetAspect(), Config->fFrustumZNear, Config->fFrustumZFar);
  228.     glViewport(rv.left, rv.top, rv.right - rv.left, rv.bottom - rv.top);
  229.     glMatrixMode(GL_MODELVIEW);
  230.  
  231.     MakeNotCurrent();
  232. }
  233.  
  234. void CEngine::Paint()
  235. {
  236.     if(World == NULL)
  237.         return;
  238.  
  239.     MakeCurrent();
  240.  
  241.     StartScene();
  242.  
  243.     SetCamera();
  244.     DrawScene();
  245.  
  246.     Start2D();
  247.     DrawInfo();
  248.     End2D();
  249.  
  250.     EndScene();
  251.  
  252.     MakeNotCurrent();
  253. }
  254.  
  255. void CEngine::LoadTextures()
  256. {
  257.     String *sWADString;
  258.  
  259.     if(World->GetWADString(&sWADString) == false)
  260.     {
  261.         txtConsole->Print("WAD string not found.\n", Color::Red);
  262.         return;
  263.     }
  264.  
  265.     MakeCurrent();
  266.     TextureManager->LoadTextures(sWADString);
  267.     MakeNotCurrent();
  268. }
  269.  
  270. void CEngine::UpdateTextureFilter()
  271. {
  272.     if(TextureManager == NULL)
  273.         return;
  274.  
  275.     MakeCurrent();
  276.     TextureManager->UpdateTextureFilter();
  277.     MakeNotCurrent();
  278. }
  279.  
  280. void CEngine::DestroyTextures()
  281. {
  282.     if(TextureManager == NULL)
  283.         return;
  284.  
  285.     MakeCurrent();
  286.     TextureManager->DestroyTextures();
  287.     MakeNotCurrent();
  288. }
  289.  
  290. void CEngine::PreRenderLoop()
  291. {
  292.     Camera->InitializePerformanceCounter();
  293. }
  294.  
  295. void CEngine::EnterRenderLoop()
  296. {
  297.     bRender = true;
  298.     PreRenderLoop();
  299.  
  300.     do
  301.     {
  302.         Application::DoEvents();
  303.  
  304.         if(System::Windows::Forms::Form::ActiveForm == NULL)
  305.         {
  306.             System::Threading::Thread::Sleep(100);
  307.             continue;
  308.         }
  309.  
  310.         MakeCurrent();
  311.  
  312.         StartScene();
  313.  
  314.         MoveCamera();
  315.         SetCamera();
  316.         CullScene();
  317.         DrawScene();
  318.  
  319.         Start2D();
  320.         DrawInfo();
  321.         End2D();
  322.  
  323.         EndScene();
  324.  
  325.         MakeNotCurrent();
  326.     }
  327.     while(bRender == true);
  328. }
  329.  
  330. void CEngine::ExitRenderLoop()
  331. {
  332.     bRender = false;
  333. }
  334.  
  335. void CEngine::SetWorld(CWorld *World, CTextureManager *TextureManager)
  336. {
  337.     World->UpdateBrushCount();
  338.  
  339.     txtConsole->Print(String::Concat(World->GetBrushCount().ToString(), S" brushes loaded.\n"), Color::Green);
  340.  
  341.     this->World = World;
  342.     this->HighlightObject = NULL;
  343.     this->PointFile = NULL;
  344.  
  345.     DestroyTextures();
  346.  
  347.     this->TextureManager = TextureManager;
  348.  
  349.     LoadTextures();
  350.  
  351.     World->UpdateColors();
  352.  
  353.     txtConsole->Print("Calculating texture coordinates.\n", Color::Gray);
  354.  
  355.     World->UpdateTexCoords(TextureManager);
  356.  
  357.     txtConsole->Print("Calculating bounding boxes.\n", Color::Gray);
  358.  
  359.     World->UpdateBoundingBoxes();
  360.  
  361.     this->Camera->Reset();
  362.  
  363.     bMousePressed = false;
  364.     bW = false;
  365.     bA = false;
  366.     bS = false;
  367.     bD = false;
  368.     bShift = false;
  369.     bUp = false;
  370.     bDown = false;
  371.     bRight = false;
  372.     bLeft = false;
  373. }
  374.  
  375. CTextureManager *CEngine::GetTextureManager()
  376. {
  377.     return this->TextureManager;
  378. }
  379.  
  380. void CEngine::SetHighlightObject(CWorldObject *HighlightObject)
  381. {
  382.     this->HighlightObject = HighlightObject;
  383. }
  384.  
  385. void CEngine::SetPointFile(CPointFile *PointFile)
  386. {
  387.     this->PointFile = PointFile;
  388. }
  389.  
  390. void CEngine::SetMousePosition(int X, int Y)
  391. {
  392.     vMouseNew.X = X;
  393.     vMouseNew.Y = Y;
  394. }
  395.  
  396. void CEngine::SetMousePressed(bool bMousePressed)
  397. {
  398.     this->bMousePressed = bMousePressed;
  399. }
  400.  
  401. void CEngine::SetKeyPressed(System::Windows::Forms::Keys Key, bool bKeyPressed)
  402. {
  403.     switch(Key)
  404.     {
  405.         case System::Windows::Forms::Keys::W:
  406.             bW = bKeyPressed;
  407.             break;
  408.         case System::Windows::Forms::Keys::A:
  409.             bA = bKeyPressed;
  410.             break;
  411.         case System::Windows::Forms::Keys::S:
  412.             bS = bKeyPressed;
  413.             break;
  414.         case System::Windows::Forms::Keys::D:
  415.             bD = bKeyPressed;
  416.             break;
  417.         case System::Windows::Forms::Keys::Up:
  418.             bUp = bKeyPressed;
  419.             break;
  420.         case System::Windows::Forms::Keys::Down:
  421.             bDown = bKeyPressed;
  422.             break;
  423.         case System::Windows::Forms::Keys::Right:
  424.             bRight = bKeyPressed;
  425.             break;
  426.         case System::Windows::Forms::Keys::Left:
  427.             bLeft = bKeyPressed;
  428.             break;
  429.         case System::Windows::Forms::Keys::ShiftKey:
  430.             bShift = bKeyPressed;
  431.             break;
  432.     }
  433. }
  434.  
  435. void CEngine::ClearBuffers()
  436. {
  437.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  438.     glLoadIdentity();
  439. }
  440.  
  441. void CEngine::MoveCamera()
  442. {
  443.     Vertex2i vMovement;
  444.     
  445.     Camera->UpdateTimeElapsed();
  446.  
  447.     vMovement.X = vMouseOld.X - vMouseNew.X;
  448.     vMovement.Y = vMouseOld.Y - vMouseNew.Y;
  449.  
  450.     if(bMousePressed)
  451.     {
  452.         Camera->MoveCameraAngles(Config->bInvertCamera ? -vMovement.Y : vMovement.Y, vMovement.X);
  453.     }
  454.  
  455.     vMouseOld.X = vMouseNew.X;
  456.     vMouseOld.Y = vMouseNew.Y;
  457.  
  458.     float fWalk = 0.0f, fStrafe = 0.0f;
  459.  
  460.     if(bW || bUp)
  461.     {
  462.         fWalk += Config->fCameraSpeed;
  463.     }
  464.  
  465.     if(bS || bDown)
  466.     {
  467.         fWalk -= Config->fCameraSpeed;
  468.     }
  469.  
  470.     if(bD || bRight)
  471.     {
  472.         fStrafe -= Config->fCameraSpeed;
  473.     }
  474.  
  475.     if(bA || bLeft)
  476.     {
  477.         fStrafe += Config->fCameraSpeed;
  478.     }
  479.  
  480.     if(bShift)
  481.     {
  482.         fWalk *= Config->fCameraBoost;
  483.         fStrafe *= Config->fCameraBoost;
  484.     }
  485.  
  486.     Camera->MoveCamera(fWalk, fStrafe);
  487. }
  488.  
  489. void CEngine::SetCamera()
  490. {
  491.     Camera->SetCamera();
  492. }
  493.  
  494. void CEngine::CullScene()
  495. {
  496.     Frustum->ResetCulled();
  497.     Frustum->CalculateFrustum();
  498.     World->CullWorld(Frustum);
  499. }
  500.  
  501. void CEngine::StartScene()
  502. {
  503.     ClearBuffers();
  504. }
  505.  
  506. void CEngine::DrawScene()
  507. {
  508.     switch(Config->eRenderMode)
  509.     {
  510.         case RenderMode::Textured:
  511.             World->DrawWorldTextured();
  512.             break;
  513.         case RenderMode::Solid:
  514.             World->DrawWorldSolid();
  515.             break;
  516.         case RenderMode::WireFrame:
  517.             World->DrawWorldWireFrame();
  518.             break;
  519.         case RenderMode::Points:
  520.             World->DrawWorldPoints();
  521.             break;
  522.     }
  523.  
  524.     if(Config->bOutlineScene)
  525.         World->Outline();
  526.  
  527.     if(Config->bDrawSelection && this->HighlightObject != NULL)
  528.         HighlightObject->Highlight(false);
  529.  
  530.     if(this->PointFile != NULL)
  531.         PointFile->DrawPoints();
  532. }
  533.  
  534. void CEngine::EndScene()
  535. {
  536.     RenderToScreen();
  537. }
  538.  
  539. void CEngine::Start2D()
  540. {
  541.     glMatrixMode(GL_PROJECTION);
  542.     glPushMatrix();
  543.     glLoadIdentity();
  544.     gluOrtho2D(0.0f, Frustum->GetWidth(), 0.0f, Frustum->GetHeight());
  545.     glScalef(1.0f, -1.0f, 1.0f);
  546.     glTranslatef(0.0f, -Frustum->GetHeight(), 0.0f);
  547.  
  548.     glMatrixMode(GL_MODELVIEW);
  549.     glPushMatrix();
  550.     glLoadIdentity();
  551.  
  552.     glDisable(GL_DEPTH_TEST);
  553.     glDisable(GL_CULL_FACE);
  554.     //glNormal3f(0.0f, 0.0f, 1.0f);
  555. }
  556.  
  557. void CEngine::DrawInfo()
  558. {
  559.     Color3uc Color;
  560.     Color.R = 255;
  561.     Color.G = 0;
  562.     Color.B = 0;
  563.  
  564.     RenderText(String::Concat(S"FPS: ", Camera->GetFPS().ToString("0.00")), 4, 4, Color);
  565.     RenderText(String::Concat(S"Brushes drawn: ", (World->GetBrushCount() - Frustum->GetCulled()).ToString(), S"/", World->GetBrushCount().ToString()), 4, 16, Color);
  566. }
  567.  
  568. void CEngine::RenderText(String *Text, int X, int Y, Color3uc Color)
  569. {
  570.     void *pText = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(Text).ToPointer();
  571.  
  572.     glColor3ub(Color.R, Color.G, Color.B);
  573.     glRasterPos2i(X, Y + 8);
  574.  
  575.     glPushAttrib(GL_LIST_BIT);
  576.     glListBase(iFontBase - 32);
  577.     glCallLists(Text->Length, GL_UNSIGNED_BYTE, pText);
  578.     glPopAttrib();
  579.  
  580.     glRasterPos2i(0, 0);
  581.  
  582.     System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr(pText)));
  583. }
  584.  
  585. void CEngine::End2D()
  586. {
  587.     glPopMatrix();
  588.     glMatrixMode(GL_PROJECTION);
  589.  
  590.     glPopMatrix();
  591.     glMatrixMode(GL_MODELVIEW);
  592. }
  593.  
  594. void CEngine::RenderToScreen()
  595. {
  596.     glFlush();
  597.     SwapBuffers(hDC);
  598. }
  599.  
  600. bool CEngine::TestExtension(String *sExtension)
  601. {
  602.     MakeCurrent();
  603.     char *szExtension = (char *)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(sExtension)).ToPointer();
  604.     
  605.     char *p = (char *)glGetString(GL_EXTENSIONS);
  606.     char *end;
  607.     int extNameLen;
  608.  
  609.     extNameLen = strlen(szExtension);
  610.     end = p + strlen(p);
  611.  
  612.     while(p < end)
  613.     {
  614.         int n = strcspn(p, " ");
  615.         if ((extNameLen == n) && (strncmp(szExtension, p, n) == 0))
  616.         {
  617.             System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)szExtension));
  618.             MakeNotCurrent();
  619.  
  620.             return true;
  621.         }
  622.         p += (n + 1);
  623.     }
  624.     
  625.     System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)szExtension));
  626.     MakeNotCurrent();
  627.  
  628.     txtConsole->Print(String::Concat("Extension ", sExtension, " not supported.\n"), Color::Red);
  629.  
  630.     return false;
  631. }